package xiaojian.toolkit.ant;

public class SelectorUtils {
	public static boolean match(String pattern, String str) {
		return match(pattern, str, true);
	}

	public static boolean match(String pattern, String str,
			boolean caseSensitive) {
		char[] patArr = pattern.toCharArray();
		char[] strArr = str.toCharArray();
		int patIdxStart = 0;
		int patIdxEnd = patArr.length - 1;
		int strIdxStart = 0;
		int strIdxEnd = strArr.length - 1;

		boolean containsStar = false;
		for (char aPatArr : patArr) {
			if (aPatArr == '*') {
				containsStar = true;
				break;
			}
		}
		if (!containsStar) {
			if (patIdxEnd != strIdxEnd) {
				return false;
			}
			for (int i = 0; i <= patIdxEnd; i++) {
				char ch = patArr[i];
				if ((ch != '?') && (different(caseSensitive, ch, strArr[i]))) {
					return false;
				}
			}
			return true;
		}
		if (patIdxEnd == 0) {
			return true;
		}
		char ch;
		for (;;) {
			ch = patArr[patIdxStart];
			if ((ch == '*') || (strIdxStart > strIdxEnd)) {
				break;
			}
			if ((ch != '?')
					&& (different(caseSensitive, ch, strArr[strIdxStart]))) {
				return false;
			}
			patIdxStart++;
			strIdxStart++;
		}
		if (strIdxStart > strIdxEnd) {
			return allStars(patArr, patIdxStart, patIdxEnd);
		}
		for (;;) {
			ch = patArr[patIdxEnd];
			if ((ch == '*') || (strIdxStart > strIdxEnd)) {
				break;
			}
			if ((ch != '?')
					&& (different(caseSensitive, ch, strArr[strIdxEnd]))) {
				return false;
			}
			patIdxEnd--;
			strIdxEnd--;
		}
		if (strIdxStart > strIdxEnd) {
			return allStars(patArr, patIdxStart, patIdxEnd);
		}
		while ((patIdxStart != patIdxEnd) && (strIdxStart <= strIdxEnd)) {
			int patIdxTmp = -1;
			for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
				if (patArr[i] == '*') {
					patIdxTmp = i;
					break;
				}
			}
			if (patIdxTmp == patIdxStart + 1) {
				patIdxStart++;
			} else {
				int patLength = patIdxTmp - patIdxStart - 1;
				int strLength = strIdxEnd - strIdxStart + 1;
				int foundIdx = -1;
				label455: for (int i = 0; i <= strLength - patLength; i++) {
					for (int j = 0; j < patLength; j++) {
						ch = patArr[(patIdxStart + j + 1)];
						if ((ch != '?')
								&& (different(caseSensitive, ch,
										strArr[(strIdxStart + i + j)]))) {
							break label455;
						}
					}
					foundIdx = strIdxStart + i;
					break;
				}
				if (foundIdx == -1) {
					return false;
				}
				patIdxStart = patIdxTmp;
				strIdxStart = foundIdx + patLength;
			}
		}
		return allStars(patArr, patIdxStart, patIdxEnd);
	}

	private static boolean allStars(char[] chars, int start, int end) {
		for (int i = start; i <= end; i++) {
			if (chars[i] != '*') {
				return false;
			}
		}
		return true;
	}

	private static boolean different(boolean caseSensitive, char ch, char other) {
		return ch != other;
	}
}
